基于Transformer fine-tune领域特定分词器
归纳使用HanLP训练基于Transformer的tokenizer的过程,写着写着发现开始介绍虚拟环境了😅
Before you read
本文的主要内容
基于 Hanlp 2.x Python API 搭建某一领域特定的分词器。
搭建 Python 虚拟开发环境。
准备少量标注数据集。
利用 HanLP 的 transformer tokenizer 对 bert-base-chinese 进行 fine-tune。
模型的保存和使用方式。
本文将不包括
Note: 本文将只把深度学习部分当作一个黑箱模型使用,如果你仍然想要对自然语言处理有更多的了解,下面是一些科普性质的资料。如果需要更深层次的理解,可能需要通过网课、教科书和论文等手段了。
神经网络的基本概念介绍,粗略的介绍可见👇:
自然语言处理的基础方法:
如果你倾向于传统的基于规则(或者语法)的语义分析手段,而对如今 NLP 中基于统计的方法存有疑虑,可参见数学之美(第三版) (豆瓣) (douban.com) 中的有关章节,322 和图书馆都有这本书。
如果你很难理解 NLP 中词向量或者词嵌入的概念,这篇博士论文或许能够帮到你。作者本人的博客也有不少词向量生成和语言模型相关的文章。
Transformer 的论文精读:
开发环境搭建
这一节内容讲解 Python 开发环境搭建和虚拟环境设置,是一个很傻瓜🤓的教程。这一节的安装配置利用到了 Annaconda,如果本机已经有了 Python 环境的话,直接跳过即可。
安装 Annaconda
长话短说,Anaconda 是一个 Python 和 R 语言的发行版本,我们这里主要使用其中的 Conda 来进行 Python 的版本管理、环境管理和包管理。其优势在于你不需要自行管理 Python 的虚拟环境和 Python 版本,省去了不少麻烦(想象一下你需要自行管理本机的 Python 2.x 和 Python 3.x 环境,在运行对 Python 版本要求不同的软件时,你可能需要手动设置 Python 有关的环境变量,这也太麻烦了😡)
Annaconda 的安装包可以直接在官网获取,如果因为国内网络环境安装太慢,可以在清华大学的镜像仓库下载。
如果你的系统恰巧是 MacOS 或 Linux,而且下载的是 shell 脚本(.sh 文件),你可能需要用类似于 chmod 的命令改变文件权限。
关于具体的文件安装,如果是可执行文件,直接运行即可,如果是 shell 脚本,命令行直接运行更加方便。
安装过程中的一些必要设置
对于 Windows,你需要注意在安装时设置将 Anaconda 的路径加入环境变量 $PATH 中,这样才能确保后面直接在 shell 使用 Conda 命令。
安装后的一些必要设置
为了保证日后下载包的速度,不妨将清华大学的镜像仓库加入 conda 设置中:
conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/free/
conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/main/
conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud/conda-forge/安装后的确认
当你安装完成后,打开 shell,应该已经能发现一些不同:你的当前命令前出现了 (base) 字样,这意味着现在我们处于一个名为 base 的虚拟环境。虚拟环境的概念我们下一小节会简单介绍。
如前所述,Anaconda 是一个 Python 和 R 语言的发行版本,在安装过程中它会:
- 自动安装一个 Python 作为其默认的 Python 版本。
- 自动安装 Conda 作为包管理工具(包管理工具这一概念我相信你已经很熟悉了,因此不赘言它的概念和好处。如果你还不熟悉的话,可以查看一些包管理器的官网,它们的介绍页面应该有更严谨翔实的说法,比如 Python 的 pip、NodeJS 的 npm、yarn,MacOS 的 homebrew,Windows 的 winget、chocolatey 和 scoop 等)。
- 自动创建一个名为 base 的 Python 虚拟环境,作为其默认的 Python 虚拟环境。
HanLP 的配置
搭建虚拟环境
Again,虚拟环境只是一个建议,它不是必选项。如果你在未来会比较频繁的进行 Python 开发,你迟早需要接触这个概念。节约时间的话完全可以跳过。
既然我们已经有了 conda 和 Python,想必安装 HanLP 之类的依赖对你来说已经不是难题了。但是为了依赖安全考虑,我们需要搭建一个新的虚拟环境,我们将在这个虚拟环境里运行我们的分词器项目。在本文档的例子里,我将这个环境命名为 tok 。
conda create -n tok
如果我们按照提示切换到 tok 环境:
conda activate tok则命令前方的 base 将变为 tok 。
为什么需要虚拟环境?
现在我们已经有了两个虚拟环境了,
base和tok,我们总算可以更实际地介绍什么是虚拟环境,以及为什么要使用虚拟环境了🎉。这小节内容完全是和教程无关的,你也可以直接跳过~
虚拟环境有点像是虚拟机的概念,它隔离的是 Python 的包和 Python 本身,也就是说,每个虚拟环境会独立存放一个 Python 包的版本,也会单独指定一个 Python 版本(sure,Python 是不会重复安装的,虚拟环境里会单独设置 python 的环境变量)。
我们下面用两个例子来说明为什么虚拟环境是必要的:
- 我们在
base下面需要用 Python2,而tok下需要 Python3,你应该知道这两个大版本的 Python 是语法不兼容的,但却会使用同一个环境变量。如果没有虚拟环境,每次我们可能都要额外指定:运行 a 脚本要用 Python2,运行 b 程序需要用 Python3。如果是用虚拟环境加以区分,则省去了指定 Python 版本的麻烦,只要在虚拟环境之间切换就可以了。 - 我们在两个虚拟环境下需要使用版本不同的同一个包,如果不使用虚拟环境,包的冲突是无法避免的。而有了虚拟环境,在两个环境里面我们可以使用不同的版本,两个项目会相安无事。此外,如果我们在虚拟环境里配置项目,一旦我们想要使用类似于
pip freeze > requirements.txt的方式导出该项目的包依赖(在写开源软件的时候这通常是必要的),我们就能确保导出的只是这个项目的包依赖,不会带上别的东西。
安装 Python、HanLP 等
万事俱备,我们可以简单使用 conda 安装一个 Python(如下面示例,这个 Python 版本可以任意指定),然后用这个 Python 的 pip 工具安装 HanLP。HanLP 相关的依赖有很多,而这些会被 pip 自动安装到当前的 tok 虚拟环境中,全然不用担心这些依赖日后和其他项目发生冲突,也不必担心日后安装了更高版本的相关依赖导致 HanLP 无法运行,只要做好虚拟环境隔离就可以~
conda install python=3.10
pip install hanlp训练领域特定分词器
我们在这一节开始真正利用 HanLP 训练分词器。在文档开始已经提到,下面并不会介绍深层次的原理,我们这里只简单的把 transformer 当作黑箱,投进去一些标注好的数据,使其能够发现规律,完成更多的分词任务即可。
需要注意的是,我们要利用的 transformer API 实际上包含一个已经进行过预训练的 bert-base-chinese 模型,这个模型已经利用通用的中文语料库训练过。问题在于,通用的语料库可能不能很好的涵盖特定领域的语料,或者特定领域语料的数量太少,在预训练时可能已经被当作噪声处理了。因此,我们实际上是在经过通用语料库预训练模型的基础上进行 fine-tune。
这里的 fine-tune 是深度学习领域的一个术语,翻译过来大概是 “微调” 的意思,它指的是我们已经有了一个经过大量数据训练的模型(比如我们的 bert-base-chinese),我们的需求(特定领域的分词)和这个大模型原本要解决的问题有了些许差异,此时我们可以保留该模型的初始权重,利用领域特定的数据集接着训练模型,使其能更好的满足我们特定领域的需求(从广而不精到领域专家)。
你可能会好奇这里的 bert-base-chinese 和 transformer 模型的关系是什么。实际上 bert 是 transformer 的一个变体,它们在 transformer 的部分实际上没什么大的区别。bert 的全称是 Bidirectional Encoder Representation from Transformers,如果你想看原论文,详细了解两者区别的话,可以点击👉这里。顺带一提,时下大火的 GPT 模型(Generative Pre-trained Transformer)也源自 transformer。如今 Google 被 Microsoft 联合 OpenAI ChatGPT 推出的 New Bing 降维打击,这一切的根源居然是 Google 自己提出的 Transformer,实在是很有戏剧性。
数据集的准备
我们的训练数据集遵照 HanLP,大概是这样的模式:
莫干山高新区 通航产业园 鼎盛路 28 号 3 号楼
永平路 与 长虹东街 交叉路口 往 北 约 150 米
浙江省 湖州市 德清县 舞阳街道 山民村 9 - 1 号 白果树
武康镇 贵和街 194 号
浙江省 湖州市 德清县 钟管镇 南湖社区 南湖路 272 号如果你要解决的不是分词问题,你需要查看 HanLP 的其他用例。
模型训练与保存
模型训练与保存的代码大概如下所示,如果需要了解每个参数意义的话,你需要参考文档最开始所说的资料研究,但是如果只是用来训练一个简单的分词器,你完全可以使用默认参数,只需要给出训练集、测试集、模型保存路径即可。
tokenizer = TransformerTaggingTokenizer()
save_dir = 'your model save path'
tokenizer.fit(
your dataset,
your dataset, # Conventionally, no devset is used. See Tian et al. (2020).
save_dir,
'bert-base-chinese',
max_seq_len=300,
char_level=True,
hard_constraint=True,
sampler_builder=SortingSamplerBuilder(batch_size=32),
epochs=3,
adam_epsilon=1e-6,
warmup_steps=0.1,
weight_decay=0.01,
word_dropout=0.1,
seed=1660853059,
)
tokenizer.evaluate(your test set, save_dir)模型训练完成之后会自动保存在 save_dir 下,保存结果会是多个文件,包含模型结构、权重信息等。
加载和使用已保存的模型
HanLP API 的调用没什么好说的,这里的 print 函数会以 list 的形式输出分词结果。
model = hanlp.load(save_dir)
print(model("湖北省武汉市珞瑜路129号"))What to do next?
如果顺利的话,你现在应该已经得到了一个领域特定的分词器,我想你可能有两件想做的事情🤔,但是这已经不是本文档的覆盖范围了,因此我简单给出一些建议:
- 训练其他模型以应对更多别的需求:
- 你可以参考 HanLP 的文档,进一步了解 HanLP 的应用。
- 或者你已经不满足于既定的模型结构,想要自行设计模型,你可以参考下面的资料:
- PyTorch、Tensorflow、paddlepaddle 等深度学习框架。
- keras 等更高级的深度学习库,它们通常会自行封装一些 layer 供你使用,让你可以直接像搭积木一样构建模型。
- 了解模型如何部署到实际项目里:
- 你可能需要参考 PyTorch 的模型部署文档,因为 HanLP 对 Transformer 的封装实际上是基于 PyTorch 实现的。
- 你可能需要参考 Python 或者其他后端编程语言搭建网络服务器的方式将模型封装成服务。